﻿using System;
using System.Linq;
using FLib;
using LibraryGuard.Interfaces;
using LibraryGuard.Interfaces.Configuration;

namespace LibraryGuard.Modes
{
	/// <summary>
	/// Interactive mode, see <see cref="LibraryGuard.Interfaces.Configuration.Mode.Interactive"/>.
	/// </summary>
	public sealed class InteractiveMode
		: BaseMode
	{
		#region Static Constructor
		static InteractiveMode()
		{
			Logger = NLog.LogManager.GetLogger("InteractiveMode");
		}
		#endregion

		#region Constructor
		public InteractiveMode(IConfiguration config, IGuard[] guards, IActionList actionList)
			: base(config, guards, actionList)
		{ }
		#endregion

		#region Overrides
		protected override void ExecuteAction(IActionInfo action)
		{
			lock (this.ActionList) //Locking on whole list gives us the ability to read input from console correctly
			{
				char userAction = 'y';
				if (action.IsEdgeAction) //Edge action, ask what to do.
				{
					Console.WriteLine("Do you want to execute action:");
					Console.WriteLine("\t" + action.ToString());
					userAction = GetUserAction("[Y]es/[n]o/[d]elay", 'y', 'n', 'd');
					Logger.Debug("User request '{0}' for edge action '{1}'", userAction, action.ToString());
				}

				if (userAction == 'y')
				{
					if (!action.Execute(this.ActionList))
					{
						Console.WriteLine("Action failed:");
						Console.WriteLine("\t" + action.ToString());
						Console.WriteLine("What do you want to do?");
						userAction = GetUserAction("[R]emove/[d]elay", 'r', 'd');
						Logger.Warn("User requested '{0}' for failed action");
					}
				}

				if (userAction == 'd')
				{
					this.RunDelayedTask(() => ExecuteAction(action));
					Logger.Debug("Action delayed");
				}
			}
		}
		#endregion

		#region Private methods
		/// <summary>
		/// Gets user action.
		/// </summary>
		/// <param name="msg"></param>
		/// <param name="allowedChars"></param>
		/// <returns></returns>
		private static char GetUserAction(string msg, params char[] allowedChars)
		{
			Console.ResetColor();
			string answer = string.Empty;
			do
			{
				Console.Write(msg + " ");
				answer = Console.ReadLine();
			} while (answer.Length < 1 || !allowedChars.Contains(char.ToLower(answer[0])));
			return char.ToLower(answer[0]);
		}
		#endregion
	}
}
